﻿#region Usings

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Mvc;

#endregion

namespace Rail.Net.Common.ActionFilters
{
    public class SetCultureAttribute : FilterAttribute, IActionFilter
    {
        #region IActionFilter Members

        public void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var cultureCode = SetCurrentLanguage(filterContext);

            if (string.IsNullOrEmpty(cultureCode))
                return;

            HttpContext.Current.Response.Cookies.Add(
                new HttpCookie("Culture", cultureCode)
                    {
                        HttpOnly = true,
                        Expires = DateTime.Now.AddYears(100)
                    }
                );

            filterContext.HttpContext.Session["Culture"] = cultureCode;

            var ci = new CultureInfo(cultureCode);
            Thread.CurrentThread.CurrentUICulture = ci;
            Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name);
        }

        public void OnActionExecuted(ActionExecutedContext filterContext)
        {
        }

        #endregion

        private static string GetCookieCulture(ActionExecutingContext filterContext, ICollection<string> cultures)
        {
            /* Get the language in the cookie*/
            var userCookie = filterContext.RequestContext
                .HttpContext
                .Request
                .Cookies["Culture"];

            if (userCookie != null)
            {
                if (!string.IsNullOrEmpty(userCookie.Value))
                {
                    if (cultures.Contains(userCookie.Value))
                    {
                        return userCookie.Value;
                    }
                    return string.Empty;
                }
                return string.Empty;
            }
            return string.Empty;
        }

        private static string GetSessionCulture(ActionExecutingContext filterContext, ICollection<string> cultures)
        {
            if (filterContext.RequestContext.HttpContext.Session["Culture"] != null)
            {
                var sessionCulture = filterContext.RequestContext.HttpContext.Session["Culture"].ToString();

                if (!string.IsNullOrEmpty(sessionCulture))
                {
                    return cultures.Contains(sessionCulture) ? sessionCulture : string.Empty;
                }
                return string.Empty;
            }
            return string.Empty;
        }

        private static string GetBrowserCulture(ActionExecutingContext
                                                    filterContext, IEnumerable<string> cultures)
        {
            /* Gets Languages from Browser */
            var browserLanguages = filterContext.RequestContext.HttpContext.Request.UserLanguages;

            if (browserLanguages != null)
            {
                foreach (
                    var culture in
                        browserLanguages.SelectMany(
                            browserLanguage => cultures.Where(culture => culture == browserLanguage)))
                {
                    return culture;
                }
            }
            return string.Empty;
        }

        private static string SetCurrentLanguage(ActionExecutingContext
                                                     filterContext)
        {
            var cookieValue = GetCookieCulture(filterContext, Constants.Cultures);

            if (string.IsNullOrEmpty(cookieValue))
            {
                var sessionValue = GetSessionCulture(filterContext, Constants.Cultures);

                if (string.IsNullOrEmpty(sessionValue))
                {
                    var browserCulture = GetBrowserCulture(filterContext, Constants.Cultures);
                    return string.IsNullOrEmpty(browserCulture)
                               ? Constants.DefaultCulture
                               : browserCulture;
                }
                return sessionValue;
            }
            return cookieValue;
        }
    }
}